举个例子：在linux系统上面获取或者本机的IP地址
ifconfig可以看到激活的网络接口的详细信息，那么肯定我们需要借助grep来过滤出IP地址了。因为服务器有多个接口，我只关心公网IP的地址，可以看到eth下面一行显示了IP地址。
ifconfig | grep eth -A 1 得到如下的结果：
eth0      Link encap:Ethernet  HWaddr 12:31:43:03:98:2C  
          inet addr:10.150.151.218  Bcast:10.150.151.255  Mask:255.255.254.0
观察到ip地址的前面是addr:这几个字符，于是再来过滤
 ifconfig | grep eth -A 1 | grep -oP 'addr:[\d\.]+' 得到新的结果：
addr:10.150.151.218
这里我们使用了-o和-P选项，指定-o是因为grep默认是显示匹配的那一行，我们只关心精确匹配的部分而不是整行。至于-P表明后面的pattern是perl兼容正则表达式，因为pcre才支持零宽断言。可以看到结果中多了addr：这几个字符，这个时候该零宽断言大显身手了。不想要addr：这几个字符，那我们就去掉他。如下方式：
 ifconfig | grep eth -A 1 | grep -oP '(?<=addr:)[\d\.]+'
注意粗体部分，这个东西的英文名字我不太清楚，但有人这样翻译：零宽度正回顾后发断言，看到这个名字能不晕吗。其实我们不关心它叫什么，我们只关心它的作用。实际操作的时候，我们可以这样做，比如我想匹配addr:后面跟一个ip地址的情况（前文所言），但我只想要ip地址。那我们先来普通的过滤得到一个带addr：的结果，最后再去掉那些我们不想要的部分就可以了。至于怎么去掉，如果是去掉模式前面的部分，用(?<=xxx)，如果是模式后面的部分，用(?=xxx)，其中xxx就是你不想要的那些内容。不太好记住？实际上是比较一致的，左边的多了一个<，正好是向左的箭头。
至于有人又说到匹配方式的问题，个人觉得也不用太关心。我们不需要去关心正则表达式的具体实现，只要记住正则是贪心的就对了。所以以下命令得到的结果也就不奇怪了。
echo 'cooking singing' | grep -oP "[a-z]*(?=ing)"        ----------->cook sing
echo 'abcdefgabc' | grep -oP '(?<=abc).*'           -----------------> defgabc
 零宽断言的作用跟正则中的锚位置相同，比如我想要寻找以abc开头的行，很自然我们会想到^abc ，同样，abc结尾的行--abc$ ，但我们并不关心^$本身，他只是我们匹配模式的锚点。零宽断言的作用正是如此，比如匹配abc后面跟了一个xxx，但我只要xxx不要abc，那么就是(?<=abc)xxx 。所谓零宽就是宽度为0，我们要抛弃掉这样的锚点。
至于负向零宽断言，意思是说在我们的锚点周围不存在这样的匹配。还是举行首和行尾的情况，我们要寻找不是abc开头的行--^[^a][^b][^c]。这次我没有自然想到，一时还没有反应过来，所谓开头不是abc的意思就是第一个字符不是a，第二个字符不是b，第三个字符不是c，我现在还只知道前面的那种写法。这句话也可以说成是，行首后面不是abc。类似的不以abc结尾的行，[^a][^b][^c]$。那我想要找abc后面不是xxx的情况呢？这就要用到零宽断言了，因为行首在正则中默认就是一个锚点，但是你自定义的abc显然不是。与零宽断言类似，只不过把=换成！就行了，比如(?
犯了一个巨大的错误。(?